#include <nds.h>
#include <stdio.h>
#include <malloc.h>
#include <fat.h>
#include <unistd.h>
#include <time.h>


#include "efs_lib.h"    // include EFS lib

#include "bitmap.h"

#include "kanjis.h"

//point our video buffer to the start of bitmap background video
u16* video_buffer = (u16*)BG_BMP_RAM_SUB(0);

void DisplayBmp(u16* video_buffer, u16* backgroundPalette, BmpFile* bmp)
{
	int i, ix, iy;
	
	//copy the palette	
	for(i = 0; i < 256; i++)
	{
		backgroundPalette[i] = RGB15(bmp->colors[i].red >> 3, bmp->colors[i].green >> 3, bmp->colors[i].blue >> 3);
	}
	 
	//copy the image
	for(iy = 0; iy < bmp->info.height; iy++)
	{
		for(ix = 0; ix < bmp->info.width / 2; ix++)
			video_buffer[iy * 128 + ix] = bmp->image[(bmp->info.height - 1 - iy) * ((bmp->info.width + 3) & ~3) / 2 + ix];
	}
}

void displayKanji(char * filepath){
    FILE* file;
    u8* buffer;
    int i, size;
    
    file = fopen(filepath, "rb");
    if(file != NULL) {
        // get file size
        fseek(file, 0, SEEK_END);
        size = ftell(file); 
        fseek(file, 0, SEEK_SET);

        buffer = (u8*)malloc(size);
        
        i = 0;
        while(i < size) {
            fread(&buffer[i], 1, 1, file);
            i++;
        }
        
        BmpFile* bmp = (BmpFile*)buffer;
        
        DisplayBmp(video_buffer, BG_PALETTE_SUB, bmp);
        
        buffer[size-1] = '\0';
        free(buffer); 
        fclose(file);
    }
    else{
    }
}

void cls(uint16 *buffer, uint16 color, int level){
	int i,j;
	for(i=0;i<SCREEN_HEIGHT;i++){
		for(j=0;j<SCREEN_WIDTH;j++){
			buffer=i*SCREEN_WIDTH+j+VRAM;
			*buffer=color;
		}
	}
        //draw the clear button
        DrawLine(25, 0, 25, 50, 31);
        DrawLine(25, 50, 0, 50, 31);
	
	//draw the next button
	DrawLine(25, 50, 25, 100, 31);
	DrawLine(25, 100, 0, 100, 31);
	
	//draw the current level bars (1 bar per 3 pixels)
	for (i=0 ; i<level ; i++){
		DrawLine(10, 110+i*3, 5, 110+i*3, 31);
	}
}

void handleKeys(int *level, int *kanji){
    scanKeys();
    //int held = keysHeld();
    int down = keysDown();
    int up = keysUp();
    
    //change level/kanjis
    if(down & KEY_A){
        (*kanji)=rand()%NB_KANJIS[*level]/2;
        displayKanji(kanjiQuestionFiles[*level][*kanji]);
    }
    if(down & KEY_B){
        if((*level)<20)
            (*level)++;
        else
            (*level)=0;
		cls(video_buffer, 0, *level);
        (*kanji)=rand()%NB_KANJIS[*level]/2;
        displayKanji(kanjiQuestionFiles[*level][*kanji]);
    }
    //questions answers
    if(down & KEY_R){
        displayKanji(kanjiAnswerFiles[*level][*kanji]);
    }
    if(up & KEY_R){
        displayKanji(kanjiQuestionFiles[*level][*kanji]);
    }
}

void DrawLine(int x1, int y1, int x2, int y2, unsigned short color)
{
    int yStep = SCREEN_WIDTH;
    int xStep = 1;      
    int xDiff = x2 - x1;
    int yDiff = y2 - y1;
 
    int errorTerm = 0;
    int offset = y1 * SCREEN_WIDTH + x1; 
    int i; 
    
    //need to adjust if y1 > y2
    if (yDiff < 0)       
    {                  
       yDiff = -yDiff;   //absolute value
       yStep = -yStep;   //step up instead of down   
    }
    
    //same for x
    if (xDiff < 0) 
    {           
       xDiff = -xDiff;            
       xStep = -xStep;            
    }        
 
    //case for changes more in X than in Y	 
    if (xDiff > yDiff) 
    {                            
       for (i = 0; i < xDiff + 1; i++)
       {                           
          VRAM_A[offset] = color;  
 
          offset += xStep;           
 
          errorTerm += yDiff;     
 
          if (errorTerm > xDiff) 
          {  
             errorTerm -= xDiff;     
             offset += yStep;        
          }
       }
    }//end if xdiff > ydiff
    //case for changes more in Y than in X
    else 
    {                       
       for (i = 0; i < yDiff + 1; i++) 
       {  
          VRAM_A[offset] = color;  
 
          offset += yStep;           
 
          errorTerm += xDiff;    
 
          if (errorTerm > yDiff) 
          {     
             errorTerm -= yDiff;  
             offset += xStep;     
 
          }
       }
    }
}





int main(void) {
    //irqInit(); //if enabled I can't draw...
    //irqEnable(IRQ_VBLANK);

    //on the main (bottom) we draw
    videoSetMode(MODE_FB0);
    //images shown on sub (up)
    videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE);
    vramSetBankC(VRAM_C_SUB_BG);
    vramSetBankA(VRAM_A_LCD);

    //main on bottom to draw on it
    lcdMainOnBottom();

    //initialisation of the sub background used to display the kanji images
    BACKGROUND_SUB.control[3] = BG_BMP8_256x256 | BG_BMP_BASE(0);
    BACKGROUND_SUB.bg3_rotation.xdy = 0;
    BACKGROUND_SUB.bg3_rotation.xdx = 1 << 8;
    BACKGROUND_SUB.bg3_rotation.ydx = 0;
    BACKGROUND_SUB.bg3_rotation.ydy = 1 << 8;
    BG_PALETTE_SUB[255] = RGB15(31,31,31);
    
    // init EFSlib & libfat
    if(EFS_Init(EFS_AND_FAT | EFS_DEFAULT_DEVICE, "fat:/KanjiDS.nds")) {
        //initialisations
        srand(time(0));
        int level = 3;
        int kanji = rand()%NB_KANJIS[level]/2;
        cls(video_buffer, 0, level);
        displayKanji(kanjiQuestionFiles[level][kanji]);
        
        touchPosition touch;
        
        //draw
        int x;
        int y;
            
        int oldX = 0;
        int oldY = 0;
        
        //main loop
        while(1) {
            //look for input and refresh accordingly
            handleKeys(&level, &kanji);
            
            //handle touch
            touchRead(&touch);
            x = touch.px;
            y = touch.py;
            
            if(!(keysDown() & KEY_TOUCH) && (keysHeld() & KEY_TOUCH) && x!=0 && y!=0)
            {
                    DrawLine(oldX, oldY, x, y, rand());
            }
            if(!(keysUp() & KEY_TOUCH) && x!=0 && y!=0)
            {
                if(x<25 && y<50){//clear
                    cls(video_buffer, 0, level);
                }
		else if(x<25 && y<100 && y>50){//next
                    cls(video_buffer, 0, level);
		    kanji=rand()%NB_KANJIS[level]/2;
                    displayKanji(kanjiQuestionFiles[level][kanji]);
                }
            }
            
            oldX = x;
            oldY = y;
            
            
            swiWaitForVBlank();
        }
    }else{
        swiWaitForVBlank();
    }
    
    return 0;
}

